package com.advertisementsystem.Filter;

import com.advertisementsystem.Dto.LoginUser;
import com.advertisementsystem.Exception.ResponseResult;
import com.advertisementsystem.utils.JwtUtils;
import com.advertisementsystem.utils.RedisCache;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.security.Key;
import java.util.Date;

@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    @Autowired
    private RedisCache redisCache;

    @Value("${jwt.token.header}")
    private String header;

    @Value("${jwt.token.prefix}")
    private String tokenPrefix;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        // 1. 添加对登录接口的判断
        String requestURI = request.getRequestURI();
        // log.info("{}",requestURI );
        if ("/user/login".equals(requestURI) || "/user/register".equals(requestURI) || "/users/reset".equals(requestURI) || "/users/reset/verify".equals(requestURI) || "/users/reset/code".equals(requestURI)) {
            filterChain.doFilter(request, response);
            return;
        }

        // 获取token
        String token = getTokenFromRequest(request);
        if (StringUtils.hasText(token)) {
            try {
                // 解析token
                Claims claims = parseToken(token);
                if (claims != null) {
                    String userId = claims.getSubject();

                    // 从redis中获取用户信息
                    LoginUser loginUser = redisCache.getCacheObject("login:" + userId);
                    if (loginUser != null) {
                        // 验证token是否过期
                        if (validateToken(claims)) {
                            // 将用户信息存入SecurityContextHolder
                            UsernamePasswordAuthenticationToken authentication =
                                    new UsernamePasswordAuthenticationToken(
                                            loginUser,
                                            null,
                                            loginUser.getAuthorities()
                                    );
                            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                            SecurityContextHolder.getContext().setAuthentication(authentication);
                        } else {
                            handleAuthenticationError(response, "Token已过期");
                            return;
                        }
                    } else {
                        handleAuthenticationError(response, "用户未登录");
                        return;
                    }
                }
            } catch (Exception e) {
                handleAuthenticationError(response, "Token解析失败");
                return;
            }
        }
        filterChain.doFilter(request, response);
    }

    /**
     * 从请求中获取token
     */
    public String getTokenFromRequest(HttpServletRequest request) {
        String bearerToken = request.getHeader(header);
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(tokenPrefix)) {
            return bearerToken.substring(tokenPrefix.length()).trim();
        }
        return null;
    }

    /**
     * 解析JWT token
     */
    private Claims parseToken(String token) {
        try {
            return Jwts.parserBuilder()
                    .setSigningKey(getSigningKey())
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取签名密钥
     */
    private Key getSigningKey() {
        byte[] keyBytes = Decoders.BASE64.decode(JwtUtils.SECRET);
        return Keys.hmacShaKeyFor(keyBytes);
    }

    /**
     * 验证token是否过期
     */
    private boolean validateToken(Claims claims) {
        try {
            return claims.getExpiration().after(new Date());
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 处理认证错误
     */
    private void handleAuthenticationError(HttpServletResponse response, String message) throws IOException {
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

        ResponseResult result = ResponseResult.error(HttpStatus.UNAUTHORIZED.value(), message);
        String json = new ObjectMapper().writeValueAsString(result);
        response.getWriter().write(json);
    }
}